package org.aceor.mddal.common.sqlparser.util;

import com.alibaba.druid.sql.ast.SQLExpr;
import com.alibaba.druid.sql.ast.expr.*;
import com.google.common.base.Strings;
import org.aceor.mddal.common.sqlparser.result.object.Column;
import org.aceor.mddal.common.sqlparser.result.object.Table;
import org.apache.commons.collections.CollectionUtils;

import java.util.Set;

/**
 * Created by lxue on 16/3/24.
 */
public class SQLParserUtil {

    public static Column buildColumnIgnoreAlias(SQLExpr expr, Set<Table> tables) {
        if (CollectionUtils.isEmpty(tables)) {
            throw new NullPointerException("sql中表不能为空");
        }
        Column column = new Column();
        if (expr instanceof SQLIdentifierExpr) {
            column.setName(((SQLIdentifierExpr) expr).getName());
        } else if (expr instanceof SQLPropertyExpr) {
            buildColumnIgnoreAliasWithPropertyOrIdentifierExpr(column, (SQLPropertyExpr) expr, tables);
        } else if (expr instanceof SQLBetweenExpr) {
            buildColumnIgnoreAliasWithPropertyOrIdentifierExpr(column, ((SQLBetweenExpr) expr).getTestExpr(), tables);
        } else if (expr instanceof SQLInListExpr) {
            buildColumnIgnoreAliasWithPropertyOrIdentifierExpr(column, ((SQLInListExpr) expr).getExpr(), tables);
        } else if (expr instanceof SQLBinaryOpExpr) {
            if (((SQLBinaryOpExpr) expr).getLeft() instanceof SQLIdentifierExpr || ((SQLBinaryOpExpr) expr).getLeft() instanceof SQLPropertyExpr) {
                buildColumnIgnoreAliasWithPropertyOrIdentifierExpr(column, ((SQLBinaryOpExpr) expr).getLeft(), tables);
            } else {
                buildColumnIgnoreAliasWithPropertyOrIdentifierExpr(column, ((SQLBinaryOpExpr) expr).getRight(), tables);
            }
        } else {
            throw new IllegalArgumentException("expr :" + expr + "类型不支持");
        }
        return column;
    }

    private static void buildColumnIgnoreAliasWithPropertyOrIdentifierExpr(Column column, SQLExpr expr, Set<Table> tables) {
        if (expr instanceof SQLPropertyExpr) {
            column.setName(((SQLPropertyExpr) expr).getSimpleName());
            String owner = ((SQLPropertyExpr) expr).getOwner().toString();
            Table table = findTableByName(owner, tables);
            if (null == table) {
                table = findTableByAlias(owner, tables);
            }
            if (null == table) {
                throw new RuntimeException("未找到对应的表,表名或别名: " + owner);
            }
            column.setTable(table);
        } else if (expr instanceof SQLIdentifierExpr) {
            column.setName(((SQLIdentifierExpr) expr).getName());
        } else {
            throw new IllegalArgumentException("expr类型 :" + expr + "不支持");
        }
    }

    public static Table findTableByName(String name, Set<Table> tables) {
        return findTable(name, tables, false);
    }

    public static Table findTableByAlias(String alias, Set<Table> tables) {
        return findTable(alias, tables, true);
    }

    private static Table findTable(String input, Set<Table> tables, boolean withAlias) {
        if (Strings.isNullOrEmpty(input)) {
            return null;
        }
        if (withAlias) {
            for (Table table : tables) {
                if (input.equals(table.getAlias())) {
                    return table;
                }
            }
        } else {
            for (Table table : tables) {
                if (input.equals(table.getName())) {
                    return table;
                }
            }
        }
        return null;
    }
}
